package models

import (
	"sync"
	"sync/atomic"
)

type Snak struct {
	Id        int    `db:"id"`
	Pid       string `db:"pid"`
	Sid		  string `db:"sid"`
	SnakType  string `db:"snaktype"`
	DataType  string `db:"datatyep"`
	DataValue string `db:"datavalue"`
}

var SkidMu sync.Mutex
var skid int32 = 0
func (sk Snak) GetId() int {
	atomic.AddInt32(&skid, 1)
	return int(skid)
}

func (sk Snak) Add() {
	_, err := Conn.Exec(`INSERT INTO snak (id, pid, sid, snaktype, datatype, datavalue) VALUES (?, ?, ?, ?, ?, ?);`, sk.Id, sk.Pid, sk.Sid, sk.SnakType, sk.DataType, sk.DataValue)
	if err != nil {
		SaveChan <- sk
	}
}

type Statement struct {
	Id   string `db:"id"`
	Eid  string `db:"eid"`
	Type string `db:"type"`
	Msid int `db:"msid"`
	Rank string `db:"rk"`
}

func (st Statement) Add() {
	_, err := Conn.Exec(`INSERT INTO statement (id, eid, type, msid, rk) VALUES (?, ?, ?, ?, ?);`, st.Id, st.Eid, st.Type, st.Msid, st.Rank)
	if err != nil {
		SaveChan <- st
	}
}

type Qualifier struct {
	Id        string `db:"id"`
	Sid       string `db:"sid"`
	Pid       string `db:"pid"`
	Hash      string `db:"hash"`
	SnakType  string `db:"snaktype"`
	DataType  string `db:"datatype"`
	DataValue string `db:"datavalue"`
}

func (q Qualifier) Add() {
	_, err := Conn.Exec(`INSERT INTO qualifier (sid, pid, hash, snaktype, datatype, datavalue) VALUES (?, ?, ?, ?, ?, ?)`, q.Sid, q.Pid, q.Hash, q.SnakType, q.DataType, q.DataValue)
	if err != nil {
		SaveChan <- q
	}
}

type Reference struct {
	Id        int    `db:"id"`
	Sid       string `db:"sid"`
	Hash      string `db:"hash"`
	SnakOrder string `db:"snakorder"`
}

var ReidMu sync.Mutex
var reid int32
func (r Reference) GetId() int {
	atomic.AddInt32(&reid, 1)
	return int(reid)
}

func (r Reference) Add() {
	_, err := Conn.Exec(`INSERT INTO reference (id, sid, hash, snakorder) VALUES (?, ?, ?, ?)`, r.Id, r.Sid, r.Hash, r.SnakOrder)
	if err != nil {
		SaveChan <- r
	}
}

type SR struct {
	Rid  int `db:"rid"`
	Skid int `db:"skid"`
}
func (sr SR) Add() {
	_, err := Conn.Exec(`INSERT INTO sr (rid, skid) VALUES (?, ?)`, sr.Rid, sr.Skid)
	if err != nil {
		SaveChan <- sr
	}
}

func create_statement() {
	snak := `CREATE TABLE snak(
		id int PRIMARY KEY,
		pid varchar(10),
		sid varchar(50),
		snaktype varchar(10),
		datatype varchar(20),
		datavalue text
		)`
	statement := `CREATE TABLE statement (
		id varchar(50) PRIMARY KEY,
		eid varchar(10),
		type varchar(10),
		msid int,
		rk varchar(50),
		CONSTRAINT fk_st1 FOREIGN KEY(msid) REFERENCES snak(id),
		CONSTRAINT fk_st2 FOREIGN KEY(eid) REFERENCES entity(id)
		)`
	qualifier := `CREATE TABLE qualifier(
		id int AUTO_INCREMENT PRIMARY KEY,
		sid varchar(50),
		pid varchar(10),
		hash varchar(50),
		snaktype varchar(20),
		datatype varchar(20),
		datavalue text,
		FOREIGN KEY(sid) REFERENCES statement(id)
		)`
	reference := `CREATE TABLE reference (
		id int PRIMARY kEY,
		sid varchar(50),
		hash varchar(50),
		snakorder text
		)`
	sr := `CREATE TABLE sr (
		rid int,
		skid int,
		PRIMARY KEY(rid, skid),
		CONSTRAINT fk_sr1 FOREIGN KEY(rid) REFERENCES reference(id),
		CONSTRAINT fk_sr2 FOREIGN KEY(skid) REFERENCES snak(id)
		)`
	Conn.MustExec(snak)
	Conn.MustExec(statement)
	Conn.MustExec(qualifier)
	Conn.MustExec(reference)
	Conn.MustExec(sr)
}

func init() {
	create_statement()
}
